package com.cxl.controller;


import com.cxl.entity.*;
import com.cxl.service.CourseService;
import com.cxl.service.RemarkService;
import com.cxl.utils.HighlightResultMapper;
import com.cxl.utils.es.EsRepository;
import com.cxl.utils.pdf.FileUtils;
import com.cxl.utils.pdf.PDFUtils;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageInfo;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.pdf.PdfWriter;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.RangeQueryBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.SortBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

@Controller
public class CourseController {

    @DubboReference
    CourseService courseService;

    @DubboReference
    RemarkService remarkService;

    @Autowired
    ElasticsearchTemplate elasticsearchTemplate;

    @Autowired
    RedisTemplate redisTemplate;

    @Autowired
    EsRepository esRepository;

    /*去登陆*/
    @RequestMapping(value = "tologin")
    public String tologin(@ModelAttribute (value = "user")User user){
        return "login";
    }

    /*登陆*/
    @ResponseBody
    @RequestMapping(value = "login")
    public MsgResult login(User user, HttpSession session){
        MsgResult result = new MsgResult();
        //先判断用户和密码是否正确
        User u = courseService.findByUser(user);
        if(u!=null){
            //判断当前登陆账户是否为指定职业
            if(u.getRole() == user.getRole()){
                //更新当前用户登陆时间
                courseService.upenddate(u.getUid());
                //将登陆用户信息存入session
                session.setAttribute("LONGUSER",u);
                result.setRole(u.getRole());
                result.setCode(200);
                result.setMsginfo("登陆成功");
            }else{
                result.setCode(501);
                result.setMsginfo("当前用户并非该角色,请重新选定");
            }
        }else{
            result.setCode(500);
            result.setMsginfo("用户名或密码错误,请重新输入");
        }
        return result;
    }


    /*Es列表*/
    @RequestMapping(value = "list")
    public String list(HttpSession session,QueryVo vo, @RequestParam(defaultValue = "1")Integer pageNum, @RequestParam(defaultValue = "3")Integer pageSize, Model model){

        //es实时同步测试用
        esRepository.deleteAll();
        if(esRepository.count() == 0){
            List<Course> courseList = courseService.findByCourseList();
            User user = (User) session.getAttribute("LONGUSER");
            courseList.forEach(x->{
                //学生是否已经报名学习该课程
                x.setApply(courseService.findByApply(x.getCid(),user.getUid()));
            });
            esRepository.saveAll(courseList);
        }

        //高亮
        String pre = "<span style='color:red'>";
        String post = "</span>";

        HighlightBuilder.Field cname = new HighlightBuilder.Field("cname").preTags(pre).postTags(post);
        cname.numOfFragments(1);    //不分片

        //联合查询
        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();

        //角色       学生+ 讲师+管理员
        if(vo.getRole()!=null){

            if(vo.getRole()==1){
                User user = (User) session.getAttribute("LONGUSER");
                queryBuilder.must(QueryBuilders.termQuery("uid",user.getUid()));
            }

            //学生
            if(vo.getRole() == 0 ){
                User user = (User) session.getAttribute("LONGUSER");
                //上架的且审核通过的课程列表
                queryBuilder.must(QueryBuilders.termQuery("state",1));
                queryBuilder.must(QueryBuilders.termQuery("check",2));
            }
        }


        //课程名称
        if(StringUtils.isNoneBlank(vo.getCname())){
            queryBuilder.must(QueryBuilders.matchQuery("cname",vo.getCname()));
        }
        //日期区间
        RangeQueryBuilder rangeQuery = QueryBuilders.rangeQuery("putdate");
        if(vo.getIndate()!=null){
            rangeQuery.from(vo.getIndate().getTime());
        }
        if(vo.getOutdate()!=null){
            rangeQuery.to(vo.getOutdate().getTime());
        }
        queryBuilder.must(rangeQuery);

        NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder()
                //条件
                .withQuery(queryBuilder)
                //分页
                .withPageable(PageRequest.of(pageNum - 1, pageSize))
                //高亮
                .withHighlightFields(cname);

        //排序
        if(vo.getMysort()!=null){
            if(vo.getMysort().equals("asc")){
                nativeSearchQueryBuilder.withSort(SortBuilders.fieldSort("number").order(SortOrder.ASC));
            }
            if(vo.getMysort().equals("desc")){
                nativeSearchQueryBuilder.withSort(SortBuilders.fieldSort("number").order(SortOrder.DESC));
            }
        }

        //构建
        NativeSearchQuery build = nativeSearchQueryBuilder.build();

        AggregatedPage<Course> courses = elasticsearchTemplate.queryForPage(build, Course.class, new HighlightResultMapper());

        Page<Course> page = new Page<>(pageNum, pageSize);
        //分页
        page.setTotal(courses.getTotalElements());
        PageInfo<Course> pg = new PageInfo<>(page);
        //数据
        pg.setList(courses.getContent());

        model.addAttribute("pg",pg);
        model.addAttribute("vo",vo);

        return "list";
    }


    /*通过 + 驳回*/
    @RequestMapping(value = "getpass")
    public String getpass(Course course){
        //返回主键
        courseService.upCheck(course);
        //同步更新数据库和ES
        esRepository.deleteById(course.getCid());
        course = courseService.findByCourseID(course.getCid());
        esRepository.save(course);

        return  "redirect:list";
    }

    /*上架 + 下架*/
    @RequestMapping(value = "getState")
    public String getState(Course course){
        //返回主键
        courseService.upState(course);
        //同步更新数据库和ES
        esRepository.deleteById(course.getCid());
        course = courseService.findByCourseID(course.getCid());
        esRepository.save(course);
        return  "redirect:list";
    }

    /*PDF导出*/
    @RequestMapping(value = "getpdf")
    public void getpdf(Integer cid, HttpServletResponse response) throws Exception {
        Course course = courseService.findByCourseID(cid);
        course.setUrl(new URL(PDFUtils.getPicPath()+course.getPic()));
        course.setStatename(course.getState()==1?"上架":"下架");
        course.setCheckname(course.getCheck()==0?"未审核":course.getCheck()==1?"未通过":"已通过");
        Document document = new Document();
        PdfWriter pdfWriter = PDFUtils.createDoc(document, PDFUtils.getFilePath() + "MyWork.pdf");
        ArrayList<Course> list = new ArrayList<>();
        list.add(course);
        PDFUtils.addTable(pdfWriter,
                new String[]{"课程序号","课程名称","发布者","课程图标","课程分类","课程发布日期","学习人数","课程视频地址","课程状态","审核状态"},
                new String[]{"cid","cname","uname","url","tname","putdate","number","video","statename","checkname"},
                list,30,800);
        document.close();
        pdfWriter.close();

        FileUtils.download(response,PDFUtils.getFilePath()+"MyWork.pdf","dow.pdf",0);
    }

    /*课程分类*/
    public List<CourseType> types(){
        List<CourseType> types = null;
        if(redisTemplate.hasKey("type")){
            types = redisTemplate.opsForList().range("type",0,-1);
        }else {
            types = courseService.findByTypes();
            redisTemplate.opsForList().rightPushAll("type",types);
        }
        return types;
    }

    /*去发布课程*/
    @RequestMapping(value = "toadd")
    public String toadd(@ModelAttribute(value = "course")Course course,Model model){
        String token = UUID.randomUUID().toString();
        redisTemplate.opsForValue().set(token,"1");
        model.addAttribute("token",token);
        model.addAttribute("types",types());
        return "add";
    }

    /*上传图片*/
    @ResponseBody
    @RequestMapping(value = "getfile")
    public String getfile(MultipartFile file) throws IOException {
        String path = PDFUtils.getInpic();
        String fileName = UUID.randomUUID().toString()+file.getOriginalFilename().toString();
        file.transferTo(new File(path,fileName));
        return "/pic/"+fileName;
    }

    /*发布课程*/
    @ResponseBody
    @RequestMapping(value = "add")
    public MsgResult add(Course course,String token){
        MsgResult result = new MsgResult();
        if(redisTemplate.hasKey(token)){
            Boolean delete = redisTemplate.delete(token);
            if(delete){
                Course c = courseService.add(course);
                //es增量同步
                c = courseService.findByCourseID(c.getCid());
                esRepository.save(c);
                result.setCode(200);
                result.setMsginfo("成功");
                return result;
            }
        }
        result.setCode(500);
        result.setMsginfo("不可重复提交");
        return result;
    }

    /*非空+唯一性效验*/
    @ResponseBody
    @RequestMapping(value = "getCname")
    public boolean getCname(String cname){
       Integer flag =  courseService.findByCname(cname);
       if(flag > 0){
           return true;
       }
       return false;
    }

    /*视频上传*/
    @RequestMapping(value = "getVideo")
    public String getVideo(Integer cid,Model model){
        Course c = courseService.findByCourseID(cid);
        model.addAttribute("c",c);
        return "video";
    }

    /*视频*/
    @ResponseBody
    @RequestMapping(value = "getvideos")
    public boolean getvideos(Course course){
        courseService.addVideo(course);
        return true;
    }

    /*课程详情*/
    @RequestMapping(value = "getdetails")
    public String getdetails(Model model,Remark remark){
        //发布评论
        if(remark.getContent()!=null && remark.getScore()!=null){
            courseService.addCom(remark);
        }

        Course course = courseService.findByCourseID(remark.getCid());
        model.addAttribute("c",course);

        //好评  中评  差评 个数统计
        Comment c = new Comment();
        c.setPraise(courseService.findByComment(course.getCid()));
        c.setMedium(courseService.findByComment1(course.getCid()));
        c.setNegative(courseService.findByComment2(course.getCid()));
        model.addAttribute("com",c);
        model.addAttribute("cid",remark.getCid());
        return "details";
    }


    /*评论*/
    @RequestMapping(value = "getcomment")
    public String getcomment(Integer rid,Integer cid, Model model){
        List<Remark> list = null;
        if(rid==1){
            list =  courseService.findByRemark(cid);
        }
        if(rid==2){
            list =  courseService.findByRemark1(cid);
        }
        if(rid==3){
            list =  courseService.findByRemark2(cid);
        }
        model.addAttribute("list",list);
        return "comment";
    }




}
